﻿package LeetCode.interview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import LeetCode.interview._104_Maximum_Depth_of_Binary_Tree.TreeNode;
import sun.tools.jar.resources.jar;
import util.LogUtils;
import util.TraverseUtils;

/*
 * 
原题　
	You are climbing a stair case. It takes n steps to reach to the top.
	
	Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
	
	Note: Given n will be a positive integer.
题目大意
	
        你正在爬楼梯。到达顶部需要n步。
	每一次你都可以爬1或2步。你能爬到顶端有多少种不同的方法?
	注意:给定n是一个正整数。
解题思路
	
		这种题目属于那种“想到解法就很快做出”的类型。n个台阶的楼梯的走法等于：
	
	[cpp] view plain copy print?
	ways(n) = ways(n-1) + ways(n-2)  
	恰好是Fibonacci数列。另外提一下，对Fibonacci数列的一个计算方法是，利用矩阵A=
	[cpp] view plain copy print?
	/     \  
	| 1 1 |  
	| 1 0 |  
	\     /  
	
	题意：爬台阶问题。每次能爬一个或两个台阶，问一个有n个台阶的话，一共有几种方法爬到顶端。

 

	思路：
	
	　　n<=1，此时只有一种。
	
	　　n>1时，对于每一个台阶i，要到达台阶，最后一步都有两种方法，从i-1迈一步，或从i-2迈一步。
	
	　　也就是说到达台阶i的方法数=达台阶i-1的方法数+达台阶i-2的方法数。所以该问题是个DP问题。
	
	d(0) = 1
	
	d(1) = 1
	
	d(2) = d(2-1) + d(2-2)
	
	d(3) = d(3-1) + d(3-2)
	
	……
	
	好吧，状态转移方程其实就是Fibonacci数列。
	
	dp[n] = dp[n-1] + dp[n-2]
	
	如果梯子有1层或者2层，dp[1] = 1, dp[2] = 2，如果梯子有0层，自然dp[0] = 0 
   
   @Type 动态规划
 * @Date 2017-09-17 13：58
 */
public class _070_Climbing_Stairs {


	/**
	 * 动态规划问题：
	 * 注：n>=0
	 * 如果梯子有1层或者2层，dp[1] = 1, dp[2] = 2，如果梯子有0层，自然dp[0] = 0 
	 * @param n
	 * @return
	 */
	public int climbStairs(int n) {
		if (n == 0)	return 0;
		if (n == 1)	return 1;		//就一层时就1种方法(爬两步)
		if (n == 2)	return 2;		//有两层时有2种方法(爬一步或两步)
		int[] rs = new int[n+1];
		rs[0] = 0;
		rs[1] = 1;
		rs[2] = 2;
		for (int i = 3; i <=n ; i++) {
			rs[i] = rs[i-2]+rs[i-1];
		}
		return rs[n];
	}

    
	public static void main(String[] args) {
		_070_Climbing_Stairs obj = new _070_Climbing_Stairs();
		for (int i = 1; i <= 10; i ++) {
			LogUtils.print(obj.climbStairs(i));
			LogUtils.br();
		}

	}

}
